package nbcp.base.utils

import nbcp.base.comm.ApiResult
import nbcp.base.extend.AsLocalDateTime
import nbcp.base.extend.AsLong
import nbcp.base.extend.HasValue
import nbcp.base.extend.toNumberString
import org.slf4j.LoggerFactory
import java.io.File
import java.nio.charset.Charset
import java.time.Duration
import java.time.LocalDateTime
import java.util.concurrent.TimeUnit

object ShellUtil {

    private val logger = LoggerFactory.getLogger(ShellUtil::class.java)


    /**
     * 生成3个临时文件:  命令-ori(用户的命令内容)   命令-exec.bat(命令 > -log.txt)   命令-log.txt
     * @param cmd 直接写命令，就像在cmd或shell里的那样！
     */
    @JvmOverloads
    @JvmStatic
    fun execRuntimeCommand(
        cmd: String,
        path: String = "",
        waitForSeconds: Int = 30,
        envs: Map<String, String> = mapOf()
    ): ApiResult<String> {
        val isWindows = System.getProperty("os.name").contains("windows", true);
        var tmpPath =
            FileUtil.resolvePath(System.getProperty("java.io.tmpdir"), "shell/" + LocalDateTime.now().toNumberString());


        var shellFile = File(tmpPath).parentFile;

        shellFile.mkdirs();

        //清理24小时以前的。
        var now = LocalDateTime.now();
        shellFile.listFiles().forEach { file ->
            if (file.isDirectory) {
                return@forEach
            }

            if (!file.nameWithoutExtension.contains("-")) {
                return@forEach
            }
            var dt = file.nameWithoutExtension.split("-").first().AsLocalDateTime();
            if (dt == null) {
                return@forEach
            }
            if (Duration.between(dt, now).toHoursPart() > 24) {
                file.delete()
            }
        }


        var oriPath = tmpPath;
        var execPath = tmpPath;
        var logPath = tmpPath + ".log";
        var executor = "";
        if (executor.isEmpty()) {
            if (isWindows) {
                execPath += "-exec.bat"
                oriPath += "-ori.bat"

                var execFile = File(execPath);
                execFile.writeText(oriPath + " > " + logPath);

            } else {
                executor = "bash"
                execPath += "-exec.sh"
                oriPath += "-ori.sh"

                var execFile = File(execPath);
                execFile.writeText(executor + " " + oriPath + " > " + logPath);
            }
        }


        var oriFile = File(oriPath);
        oriFile.writeText(cmd);

        var processBuilder: ProcessBuilder? = null;

        if (executor.HasValue) {
            processBuilder = ProcessBuilder(executor, execPath)
        } else {
            processBuilder = ProcessBuilder(execPath)
        }


        if (envs.any()) {
            var penv = processBuilder.environment()
            penv.putAll(envs)
        }

        if (path.HasValue) {
            var d = File(path);
            if (d.exists()) {
                processBuilder.directory(d);
            }
        }
        processBuilder.redirectErrorStream(true)

        var process = processBuilder.start();


        if (process.waitFor(waitForSeconds.AsLong(), TimeUnit.SECONDS)) {
            var text = "";

            if (isWindows) {
                text = File(logPath).readText(Charset.forName("GBK"));
            } else {
                text = File(logPath).readText();
            }


            if (process.exitValue() == 0) {
                return ApiResult.of(text)
            }
            return ApiResult.error(text)
        } else {
            return ApiResult.error("执行脚本超时")
        }
    }
}